#ifndef ALFS_GUI_INVOCABLEUSERCOMMANDTREE_H
#define ALFS_GUI_INVOCABLEUSERCOMMANDTREE_H

// File [alfs/gui/InvocableUserCommandTree.h].
//
// InvocableUserCommandTree
//
// An InvocableUserCommandTree is a tree of InvocableUserCommand instances.  For
// example, it can represent a hierarchical menu structure.
//
// (c) copyright Alf P. Steinbach 2008.
// Use, modification and distribution are subject to the "New BSD License"
// as listed at <url: http://www.opensource.org/licenses/bsd-license.php>.

#include    "InvocableUserCommand.h"            // alfs::UserCommand
#include    <vector>                            // std::vector

namespace alfs{

#   define  ThisClass       InvocableUserCommandTree

    class ThisClass
    {
    public:
        typedef AutoNewPtr<ThisClass>   Ptr;

    private:
        class NodePtr
        {
        private:
            ThisClass::Ptr              myTree;
            InvocableUserCommand::Ptr   myCommand;

            void assertInvariant() const    { assert( myTree.isVoid() != myCommand.isVoid() ); }

        public:
            NodePtr( InvocableUserCommand::Ptr command );
            NodePtr( ThisClass::Ptr tree );

            bool isTree() const;
            bool isCommand() const;

            ThisClass::Ptr tree() const;
            InvocableUserCommand::Ptr command() const;
        };

        typedef std::vector<NodePtr>    NodePtrVector;

        std::wstring        myDefaultText;
        NodePtrVector       myNodes;

        void assertInvariant() const        { assert( myDefaultText.length() > 0 ); }

        ThisClass( ThisClass const& );                  // No such.
        ThisClass& operator=( ThisClass const& );       // No such.

    protected:
        virtual ~ThisClass();

    public:
        typedef NodePtrVector::const_iterator   const_iterator;
        typedef const_iterator                  Iterator;

        ThisClass( std::wstring const& defaultTitle );

        std::wstring text() const;

        // The following add functions return the argument for convenience.
        ThisClass::Ptr addChild( ThisClass::Ptr tree );
        InvocableUserCommand::Ptr addChild( InvocableUserCommand::Ptr command );

        std::size_t nChildren() const;
        NodePtr const& childAt( std::size_t i ) const;

        // Iteration over first level children, not over the complete tree:
        Iterator begin() const;
        Iterator end() const;
    };

    template< typename NodeContent >
    ThisClass::Ptr const& operator<<(
        ThisClass::Ptr const&   tree,
        NodeContent const&      nodeContent
        )
    {
        tree->addChild( nodeContent );
        return tree;
    }
#   undef   ThisClass
}  // alfs

#endif
